import { RegisterCmd, UpdateUserCmd } from "./../../dto/user/index";
import { User } from "../../dto";
import { BizError } from "../../enums/ErrorsEnum";
import {
  getTableRecordsSearch,
  FeiShuTable,
  Condition,
  FSBitableQuery,
  QUERTY_CONJUNCTION,
  QUERTY_OPERATOR,
  saveTableRecords,
  updateTableRecords,
} from "../../infra";
import CryptoJS from "crypto-js";
import _ from "lodash";

/**
 * 根据用户名查询用户
 * @param username 用户名
 * @returns 用户对象
 */
export async function getUserByUsername(username: string): Promise<User> {
  return convertData([await getUserRecord(username)])[0];
}

/**
 * 根据ID查询用户
 * @param id 用户ID
 * @returns 用户对象
 */
export async function getUserById(id : string): Promise<User> {
    const condition: Condition = getIdCondition(id);

    const query: FSBitableQuery = {
      field_names: ["id", "username", "name", "email", "is_admin", "password"],
      filter: {
        conditions: [condition],
        conjunction: QUERTY_CONJUNCTION.AND,
      },
    };
    const data = await getTableRecordsSearch(FeiShuTable.User, query);
    return convertData([data.items[0]])[0];
}

/**
 * 密码验证
 * @param username 用户名
 * @param password 密码明文
 * @returns 密码是否正确
 */
export async function checkPassword(
  username: string,
  password: string
): Promise<boolean> {
  const data = await getUserRecord(username);
  if (!data || data.length == 0) throw new BizError("该用户不存在");
  const pass = CryptoJS.SHA256(password).toString();
  return _.isEqual(pass, data.fields.password[0].text);
}

/**
 * 创建用户
 * @param cmd 用户注册对象
 */
export async function createUser(cmd: RegisterCmd) {
  const data = await getUserRecord(cmd.username);
  if (data) throw new BizError("用户名已存在");

  cmd.password = CryptoJS.SHA256(cmd.password).toString();
  await saveTableRecords(FeiShuTable.User, {
    ...cmd,is_admin: 0
  });
}

/**
 * 更新用户数据
 * @param cmd 更新用户对象
 * @param username 用户名
 */
export async function updateUser(cmd: UpdateUserCmd,username: string) {
    const user = await getUserRecord(username);
    if (!user) throw new BizError("该用户不存在");
    const recordId = user.record_id;
    await updateTableRecords(FeiShuTable.User,cmd,recordId);
}

/**
 * 更新用户密码
 * @param username 用户名
 * @param password 新密码明文
 */
export async function updatePassword(username: string,password: string) {
    const user = await getUserRecord(username);
    if (!user) throw new BizError("该用户不存在");
    const recordId = user.record_id;
    await updateTableRecords(FeiShuTable.User,{"password": CryptoJS.SHA256(password).toString()},recordId);
}

async function getUserRecord(username: string) {
    const condition: Condition = getUsernameCondition(username);

    const query: FSBitableQuery = {
      field_names: ["id", "username", "name", "email", "is_admin", "password"],
      filter: {
        conditions: [condition],
        conjunction: QUERTY_CONJUNCTION.AND,
      },
    };
    const data = await getTableRecordsSearch(FeiShuTable.User, query);
    return data.items[0];
}

function getUsernameCondition(username: string): Condition {
  return {
    field_name: "username",
    operator: QUERTY_OPERATOR.IS,
    value: [username],
  };
}

function getIdCondition(id:string): Condition {
  return {
    field_name: "id",
    operator: QUERTY_OPERATOR.IS,
    value: [id]
  }
}

function convertData(items: any[]): User[] {
  const users: User[] = [];
  if (!items) return [];
  for (const item of items) {
    const data = item.fields;
    const user: User = {
      id: data.id,
      username: data.username[0].text,
      email: !_.isEmpty(data.email) ? data.email[0].text : null,
      name: data.name[0].text,
      isAdmin: data.is_admin == 1,
    };
    users.push(user);
  }
  return users;
}
